from datetime import datetime
from collections.abc import Callable
from threading import Thread
from typing import Any
import logging
import os
import json
from pathlib import Path

# ⚠️ CRITICAL: 在导入xtquant之前检查client模式
# 不能依赖SETTINGS，因为main.py在导入模块后才配置SETTINGS
# 必须直接读取config.json文件
_is_client_mode = False
try:
    # 尝试查找 config.json 文件
    possible_config_paths = [
        Path.cwd() / "config.json",  # 当前工作目录
        Path.cwd() / "liugejiao_qt" / "config.json",  # 项目目录
        Path(__file__).parent.parent.parent / "liugejiao_qt" / "config.json",  # 相对于vnpy_xt的路径
    ]
    
    config_data = None
    for config_path in possible_config_paths:
        if config_path.exists():
            with open(config_path, 'r', encoding='utf-8') as f:
                config_data = json.load(f)
                print(f"🔧 [xt_gateway] 找到配置文件: {config_path}")
                break
    
    if config_data:
        datafeed_username = config_data.get("datafeed", {}).get("username", "")
        _is_client_mode = datafeed_username == "client"
        if _is_client_mode:
            # Use hardcoded values since SETTINGS is not available yet
            os.environ["XT_LOCAL_MODE"] = '1'
            os.environ["XT_DISABLE_REMOTE"] = '1'
            print(f"🔧 [xt_gateway] Client模式环境配置完成 (username='{datafeed_username}')")
        else:
            print(f"🔧 [xt_gateway] Token模式 (username='{datafeed_username}')")
except Exception as e:
    print(f"⚠️  [xt_gateway] 无法读取配置文件: {e}")
    _is_client_mode = False

from xtquant import (
    xtdata,
    xtdatacenter as xtdc
)

# ⚠️ CRITICAL: Client模式下立即清空远程服务器列表（必须在任何xtdata操作之前）
if _is_client_mode:
    try:
        # 方法1: 清空允许的优化地址
        xtdc.set_allow_optmize_address([])
        print("✅ [xt_gateway] 已清空远程服务器列表（Client模式）")
        
        # 方法2: 尝试禁用自动连接远程服务器的功能
        try:
            # 如果xtdc有这些属性，设置为False
            if hasattr(xtdc, '_auto_connect'):
                pass  # xtdc._auto_connect = False
            # if hasattr(xtdc, 'auto_connect'):
            #     # xtdc.auto_connect = False
        except:
            # Pass silently
            pass
            
        # 方法3: Monkey patch xtdc.init to prevent remote initialization
        _original_xtdc_init = xtdc.init
        def _client_mode_init(*args, **kwargs):
            print("⚠️  [xt_gateway] 拦截xtdc.init()调用（Client模式下禁止远程初始化）")
            return None
        xtdc.init = _client_mode_init
        print("✅ [xt_gateway] 已拦截xtdc.init()方法")
        
    except Exception as e:
        print(f"⚠️  [xt_gateway] 清空远程服务器列表时出错: {e}")

# Import settings after importing xtquant
from vnpy.trader.setting import SETTINGS
from xtquant import xtconstant
from xtquant.xttrader import XtQuantTrader, XtQuantTraderCallback
from xtquant.xttype import (
    StockAccount,
    XtAsset,
    XtOrder,
    XtPosition,
    XtTrade,
    XtOrderResponse,
    XtCancelOrderResponse,
    XtOrderError,
    XtCancelError
)
from filelock import FileLock, Timeout

from vnpy.event import EventEngine, EVENT_TIMER, Event
from vnpy.trader.gateway import BaseGateway
from vnpy.trader.object import (
    OrderRequest,
    CancelRequest,
    SubscribeRequest,
    ContractData,
    TickData,
    HistoryRequest,
    OptionType,
    OrderData,
    Status,
    Direction,
    OrderType,
    AccountData,
    PositionData,
    TradeData,
    Offset
)

from .xt_request import (
    XtSubscribeRequest,
    XtL2SubscribeRequest,
    XtWholeQuoteRequest,
    PERIOD_VT2XT,
    DIVIDEND_TYPE_DESC
)
from vnpy.trader.constant import (
    Exchange,
    Product
)
from vnpy.trader.utility import (
    ZoneInfo,
    get_file_path,
    round_to
)

from .xt_config import VIP_ADDRESS_LIST, LISTEN_PORT


# 交易所映射
EXCHANGE_VT2XT: dict[Exchange, str] = {
    Exchange.SSE: "SH",
    Exchange.SZSE: "SZ",
    Exchange.BSE: "BJ",
    Exchange.SHFE: "SF",
    Exchange.CFFEX: "IF",
    Exchange.INE: "INE",
    Exchange.DCE: "DF",
    Exchange.CZCE: "ZF",
    Exchange.GFEX: "GF",
}

EXCHANGE_XT2VT: dict[str, Exchange] = {v: k for k, v in EXCHANGE_VT2XT.items()}
EXCHANGE_XT2VT["SHO"] = Exchange.SSE
EXCHANGE_XT2VT["SZO"] = Exchange.SZSE


# 委托状态映射
STATUS_XT2VT: dict[int, Status] = {
    xtconstant.ORDER_UNREPORTED: Status.SUBMITTING,
    xtconstant.ORDER_WAIT_REPORTING: Status.SUBMITTING,
    xtconstant.ORDER_REPORTED: Status.NOTTRADED,
    xtconstant.ORDER_REPORTED_CANCEL: Status.CANCELLED,
    xtconstant.ORDER_PARTSUCC_CANCEL: Status.CANCELLED,
    xtconstant.ORDER_PART_CANCEL: Status.CANCELLED,
    xtconstant.ORDER_CANCELED: Status.CANCELLED,
    xtconstant.ORDER_PART_SUCC: Status.PARTTRADED,
    xtconstant.ORDER_SUCCEEDED: Status.ALLTRADED,
    xtconstant.ORDER_JUNK: Status.REJECTED
}

# 多空方向映射
DIRECTION_VT2XT: dict[tuple[Direction, Offset], int] = {
    (Direction.LONG, Offset.NONE): xtconstant.STOCK_BUY,
    (Direction.SHORT, Offset.NONE): xtconstant.STOCK_SELL,
    (Direction.LONG, Offset.OPEN): xtconstant.STOCK_OPTION_BUY_OPEN,
    (Direction.LONG, Offset.CLOSE): xtconstant.STOCK_OPTION_BUY_CLOSE,
    (Direction.SHORT, Offset.OPEN): xtconstant.STOCK_OPTION_SELL_OPEN,
    (Direction.SHORT, Offset.CLOSE): xtconstant.STOCK_OPTION_SELL_CLOSE,
}
DIRECTION_XT2VT: dict[int, tuple[Direction, Offset]] = {v: k for k, v in DIRECTION_VT2XT.items()}

POSDIRECTION_XT2VT: dict[int, Direction] = {
    xtconstant.DIRECTION_FLAG_BUY: Direction.LONG,
    xtconstant.DIRECTION_FLAG_SELL: Direction.SHORT
}

# 委托类型映射
ORDERTYPE_VT2XT: dict[tuple, int] = {
    (Exchange.SSE, OrderType.LIMIT): xtconstant.FIX_PRICE,
    (Exchange.SZSE, OrderType.LIMIT): xtconstant.FIX_PRICE,
    (Exchange.BSE, OrderType.LIMIT): xtconstant.FIX_PRICE,
}
ORDERTYPE_XT2VT: dict[int, OrderType] = {
    50: OrderType.LIMIT,
}

# 其他常量
CHINA_TZ = ZoneInfo(SETTINGS.get("timezone.china", "Asia/Shanghai"))       # 中国时区


# 全局缓存字典
symbol_contract_map: dict[str, ContractData] = {}       # 合约数据
symbol_limit_map: dict[str, tuple[float, float]] = {}   # 涨跌停价


class XtGateway(BaseGateway):
    """
    VeighNa gateway for Xueqiu QMT real-time market data interface.
    """

    default_name: str = "XT"

    default_setting: dict[str, Any] = {
        "token": "",
        "股票市场": ["是", "否"],
        "期货市场": ["是", "否"],
        "期权市场": ["是", "否"],
        "仿真交易": ["是", "否"],
        "账号类型": ["股票", "股票期权"],
        "QMT路径": "",
        "资金账号": ""
    }

    exchanges: list[Exchange] = list(EXCHANGE_VT2XT.keys())

    def __init__(self, event_engine: EventEngine, gateway_name: str) -> None:
        """构造函数"""
        super().__init__(event_engine, gateway_name)

        self.md_api: XtMdApi = XtMdApi(self)
        self.td_api: XtTdApi = XtTdApi(self)

        self.trading: bool = False
        self.orders: dict[str, OrderData] = {}
        self.trades: dict[str, TradeData] = {}
        self.count: int = 0

        self.thread: Thread | None = None
        
        # 创建专用的 logger，使用标准 logging 模块
        self._logger = logging.getLogger("XtGateway")
    
    def write_log(self, msg: str) -> None:
        """输出日志 - 重写以使用标准 logging"""
        self._logger.info(msg)
        # 仍然调用父类方法以保持 VNPy 的事件机制
        super().write_log(msg)

    def connect(self, setting: dict) -> None:
        """连接交易接口"""
        if self.thread:
            return

        self.thread = Thread(target=self._connect, args=(setting,))
        self.thread.start()

    def _connect(self, setting: dict) -> None:
        """连接交易接口 - 增强错误处理和日志"""
        import os
        import time
        import traceback
        
        try:
            token: str = setting["token"]

            stock_active: bool = setting["股票市场"] == "是"
            futures_active: bool = setting["期货市场"] == "是"
            option_active: bool = setting["期权市场"] == "是"

            self.md_api.connect(token, stock_active, futures_active, option_active)

            self.trading = setting["仿真交易"] == "是"
            if self.trading:
                # 使用完整的QMT路径，不强制使用userdata_mini目录
                path: str = setting["QMT路径"]
                
                # 验证路径是否存在
                if not os.path.exists(path):
                    self.write_log(f"警告: QMT路径不存在: {path}")
                else:
                    self.write_log(f"QMT路径存在: {path}")
                    # 检查是否包含xtquant库
                    xtquant_path = os.path.join(path, "xtquant")
                    if os.path.exists(xtquant_path):
                        self.write_log(f"找到xtquant库: {xtquant_path}")
                    else:
                        self.write_log(f"警告: 未找到xtquant库: {xtquant_path}")
                        # 尝试使用userdata_mini目录
                        userdata_mini_path = os.path.join(path, "userdata_mini")
                        if os.path.exists(userdata_mini_path):
                            self.write_log(f"找到userdata_mini目录: {userdata_mini_path}")
                            path = userdata_mini_path
                        else:
                            self.write_log(f"警告: 未找到userdata_mini目录: {userdata_mini_path}")
            
            # 初始化定时查询任务
            self.write_log("初始化定时查询任务...")
            self.init_query()
            
            if self.trading:
                self.write_log(f"准备连接交易接口，使用路径: {path}")
                
                accountid: str = setting["资金账号"]
                self.write_log(f"资金账号: {accountid}")

                if setting["账号类型"] == "股票":
                    account_type: str = "STOCK"
                else:
                    account_type = "STOCK_OPTION"
                
                self.write_log(f"账号类型: {account_type}")

                # 连接交易接口
                self.write_log("正在连接交易接口...")
                connect_result = self.td_api.connect(path, accountid, account_type)
                self.write_log(f"交易接口连接结果: {connect_result}")
                
                # 添加延迟，确保连接稳定后再进行初始化查询
                self.write_log("等待连接稳定...")
                time.sleep(3)
                
                # 显式调用初始化查询，确保触发查询
                self.write_log("开始显式初始化查询...")
                self.query_account()
                time.sleep(1)
                self.query_position()
                time.sleep(1)
                self.query_order()
                time.sleep(1)
                self.query_trade()
                self.write_log("初始化查询完成")
            else:
                self.write_log("非交易模式，跳过交易接口连接")
        except Exception as e:
            self.write_log(f"连接过程发生异常: {str(e)}")
            self.write_log(f"异常堆栈: {traceback.format_exc()}")

    def subscribe(self, req: SubscribeRequest) -> None:
        """订阅行情"""
        self.md_api.subscribe(req)

    def send_order(self, req: OrderRequest) -> str:
        """委托下单"""
        if self.trading:
            return self.td_api.send_order(req)
        else:
            return ""

    def cancel_order(self, req: CancelRequest) -> None:
        """委托撤单"""
        if self.trading:
            self.td_api.cancel_order(req)

    def query_account(self) -> None:
        """查询资金"""
        if self.trading:
            self.td_api.query_account()

    def query_position(self) -> None:
        """查询持仓"""
        if self.trading:
            self.td_api.query_position()
            
    def query_order(self) -> None:
        """查询委托信息"""
        if self.trading:
            self.td_api.query_order()
    
    def query_trade(self) -> None:
        """查询成交信息"""
        if self.trading:
            self.td_api.query_trade()

    def query_history(self, req: HistoryRequest) -> None:
        """查询历史数据"""
        return None

    def on_order(self, order: OrderData) -> None:
        """推送委托数据"""
        self.orders[order.orderid] = order
        super().on_order(order)
    
    def on_trade(self, trade: TradeData) -> None:
        """推送成交数据"""
        self.trades[trade.tradeid] = trade
        super().on_trade(trade)

    def get_order(self, orderid: str) -> OrderData:
        """查询委托数据"""
        return self.orders.get(orderid, None)  # type: ignore

    def close(self) -> None:
        """关闭接口"""
        if self.trading:
            self.td_api.close()

    def process_timer_event(self, event: Event) -> None:
        """定时事件处理"""
        self.count += 1
        if self.count < 2:
            return
        self.count = 0

        func = self.query_functions.pop(0)
        func()
        self.query_functions.append(func)

    def init_query(self) -> None:
        """初始化查询任务"""
        self.query_functions: list = [self.query_account, self.query_position, self.query_order, self.query_trade]
        self.event_engine.register(EVENT_TIMER, self.process_timer_event)

    def query_contracts(self) -> list[ContractData]:
        """
        Query all available contracts from the gateway.
        
        This method queries all available contracts from the QMT gateway,
        including stocks, ETFs, indices, and other instruments from Shanghai
        and Shenzhen exchanges.
        
        Returns:
            list[ContractData]: List of all available contracts
        """
        # Query contracts if not already done
        if not symbol_contract_map:
            self.md_api.query_stock_contracts()
            
        # Return all contracts
        return list(symbol_contract_map.values())


class XtMdApi:
    """行情API"""

    lock_filename = "xt_lock"
    lock_filepath = get_file_path(lock_filename)

    def __init__(self, gateway: XtGateway) -> None:
        """构造函数"""
        self.gateway: XtGateway = gateway
        self.gateway_name: str = gateway.gateway_name

        self.inited: bool = False
        self.subscribed: set = set()

        self.token: str = ""
        self.stock_active: bool = False
        self.futures_active: bool = False
        self.option_active: bool = False
        
        # 创建专用的 logger
        self._logger = logging.getLogger("XtMdApi")

    def onMarketData(self, data: dict) -> None:
        """行情推送回调"""
        for xt_symbol, buf in data.items():
            for d in buf:
                symbol, xt_exchange = xt_symbol.split(".")
                exchange = EXCHANGE_XT2VT[xt_exchange]

                tick: TickData = TickData(
                    symbol=symbol,
                    exchange=exchange,
                    datetime=generate_datetime(d["time"]),
                    volume=d["volume"],
                    turnover=d["amount"],
                    open_interest=d["openInt"],
                    gateway_name=self.gateway_name
                )

                contract = symbol_contract_map[tick.vt_symbol]
                tick.name = contract.name

                bp_data: list = d["bidPrice"]
                ap_data: list = d["askPrice"]
                bv_data: list = d["bidVol"]
                av_data: list = d["askVol"]

                tick.bid_price_1 = round_to(bp_data[0], contract.pricetick)
                tick.bid_price_2 = round_to(bp_data[1], contract.pricetick)
                tick.bid_price_3 = round_to(bp_data[2], contract.pricetick)
                tick.bid_price_4 = round_to(bp_data[3], contract.pricetick)
                tick.bid_price_5 = round_to(bp_data[4], contract.pricetick)

                tick.ask_price_1 = round_to(ap_data[0], contract.pricetick)
                tick.ask_price_2 = round_to(ap_data[1], contract.pricetick)
                tick.ask_price_3 = round_to(ap_data[2], contract.pricetick)
                tick.ask_price_4 = round_to(ap_data[3], contract.pricetick)
                tick.ask_price_5 = round_to(ap_data[4], contract.pricetick)

                tick.bid_volume_1 = bv_data[0]
                tick.bid_volume_2 = bv_data[1]
                tick.bid_volume_3 = bv_data[2]
                tick.bid_volume_4 = bv_data[3]
                tick.bid_volume_5 = bv_data[4]

                tick.ask_volume_1 = av_data[0]
                tick.ask_volume_2 = av_data[1]
                tick.ask_volume_3 = av_data[2]
                tick.ask_volume_4 = av_data[3]
                tick.ask_volume_5 = av_data[4]

                tick.last_price = round_to(d["lastPrice"], contract.pricetick)
                tick.open_price = round_to(d["open"], contract.pricetick)
                tick.high_price = round_to(d["high"], contract.pricetick)
                tick.low_price = round_to(d["low"], contract.pricetick)
                tick.pre_close = round_to(d["lastClose"], contract.pricetick)

                if tick.vt_symbol in symbol_limit_map:
                    tick.limit_up, tick.limit_down = symbol_limit_map[tick.vt_symbol]

                # 判断收盘状态
                tick.extra = {
                    "raw": d,
                    "market_closed": False,
                }

                # 非衍生品可以通过openInt字段判断证券状态
                if contract.product not in {Product.FUTURES, Product.OPTION}:
                    tick.extra["market_closed"] = d["openInt"] == 15
                # 衍生品该字段为持仓量，需要通过结算价判断
                elif d["settlementPrice"] > 0:
                    tick.extra["market_closed"] = True

                self.gateway.on_tick(tick)

    def connect(
        self,
        token: str,
        stock_active: bool,
        futures_active: bool,
        option_active: bool
    ) -> None:
        """连接"""
        self.gateway.write_log("开始启动行情服务，请稍等")
        self._logger.info("开始启动行情服务，请稍等")

        self.token = token
        self.stock_active = stock_active
        self.futures_active = futures_active
        self.option_active = option_active

        if self.inited:
            msg = "行情接口已经初始化，请勿重复操作"
            self.gateway.write_log(msg)
            self._logger.warning(msg)
            return

        try:
            # 检查是否使用 client 模式
            datafeed_username = SETTINGS.get("datafeed.username", "")
            
            if datafeed_username == "client":
                # Client模式: 使用本地QMT客户端，不初始化远程连接
                self.gateway.write_log("🔗 使用Client模式 - 连接本地QMT客户端")
                self._logger.info("使用Client模式 - 连接本地QMT客户端")
                # 不调用 init_xtdc()，避免连接远程服务器
                # xtdata 会自动检测本地 QMT 客户端
            else:
                # Token模式: 使用Token连接远程服务器
                self.gateway.write_log(f"🔗 使用Token模式 - 连接远程服务器")
                self._logger.info(f"使用Token模式 - 连接远程服务器")
                self.init_xtdc()

            # 尝试查询合约信息，确认连接成功
            test_result = xtdata.get_instrument_detail("000001.SZ")
            if not test_result:
                self.gateway.write_log("⚠️  查询合约返回空数据")
                self._logger.warning("查询合约返回空数据")
                
        except Exception as ex:
            msg = f"❌ 迅投研数据服务初始化失败，发生异常：{ex}"
            self.gateway.write_log(msg)
            self._logger.error(msg)
            
            if datafeed_username == "client":
                self.gateway.write_log("")
                self.gateway.write_log("💡 Client模式需要:")
                self.gateway.write_log("   1. 确保 XtMiniQmt.exe 正在运行")
                self.gateway.write_log("   2. 确保已登录账户")
                self.gateway.write_log("   3. 等待QMT客户端完全启动 (10-30秒)")
                self.gateway.write_log("   4. 检查config.json中datafeed配置:")
                self.gateway.write_log("      - username: \"client\"")
                self.gateway.write_log("      - password: \"\" (留空)")
            return

        self.inited = True

        msg = "✅ 行情接口连接成功"
        self.gateway.write_log(msg)
        self._logger.info(msg)

        self.query_contracts()

    def get_lock(self) -> bool:
        """获取文件锁，确保单例运行"""
        self.lock = FileLock(self.lock_filepath)

        try:
            self.lock.acquire(timeout=1)
            return True
        except Timeout:
            return False

    def init_xtdc(self) -> None:
        """初始化xtdc服务进程"""
        if not self.get_lock():
            return

        # 设置token
        xtdc.set_token(self.token)

        # 设置连接池
        xtdc.set_allow_optmize_address(VIP_ADDRESS_LIST)

        # 开启使用期货真实夜盘时间
        xtdc.set_future_realtime_mode(True)

        # 执行初始化，但不启动默认58609端口监听
        xtdc.init(False)

        # 设置监听端口
        xtdc.listen(port=LISTEN_PORT)

    def query_contracts(self) -> None:
        """查询合约信息"""
        if self.stock_active:
            self.query_stock_contracts()

        if self.futures_active:
            self.query_future_contracts()

        if self.option_active:
            self.query_option_contracts()

        self.gateway.write_log("合约信息查询成功")
        self._logger.info("合约信息查询成功")

    def query_stock_contracts(self) -> None:
        """查询股票合约信息"""
        xt_symbols: list[str] = []
        markets: list = [
            "沪深A股",
            "沪深转债",
            "沪深ETF",
            "沪深指数",
            "京市A股"
        ]

        for i in markets:
            names: list = xtdata.get_stock_list_in_sector(i)
            xt_symbols.extend(names)

        for xt_symbol in xt_symbols:
            # 筛选需要的合约
            product = None
            symbol, xt_exchange = xt_symbol.split(".")

            if xt_exchange == "SZ":
                if xt_symbol.startswith("00"):
                    product = Product.EQUITY
                elif xt_symbol.startswith("159"):
                    product = Product.FUND
                else:
                    product = Product.INDEX
            elif xt_exchange == "SH":
                if xt_symbol.startswith(("60", "68")):
                    product = Product.EQUITY
                elif xt_symbol.startswith("51"):
                    product = Product.FUND
                else:
                    product = Product.INDEX
            elif xt_exchange == "BJ":
                product = Product.EQUITY

            if not product:
                continue

            # 生成并推送合约信息
            data: dict = xtdata.get_instrument_detail(xt_symbol) or {}
            if data is None:
                self.gateway.write_log(f"合约{xt_symbol}信息查询失败")
                continue

            contract: ContractData = ContractData(
                symbol=symbol,
                exchange=EXCHANGE_XT2VT[xt_exchange],
                name=data["InstrumentName"],
                product=product,
                size=data["VolumeMultiple"],
                pricetick=data["PriceTick"],
                history_data=False,
                gateway_name=self.gateway_name
            )

            symbol_contract_map[contract.vt_symbol] = contract
            symbol_limit_map[contract.vt_symbol] = (data["UpStopPrice"], data["DownStopPrice"])

            self.gateway.on_contract(contract)

    def query_future_contracts(self) -> None:
        """查询期货合约信息"""
        xt_symbols: list[str] = []
        markets: list = [
            "中金所期货",
            "上期所期货",
            "能源中心期货",
            "大商所期货",
            "郑商所期货",
            "广期所期货"
        ]

        for i in markets:
            names: list = xtdata.get_stock_list_in_sector(i)
            xt_symbols.extend(names)

        for xt_symbol in xt_symbols:
            # 筛选需要的合约
            product = None
            symbol, xt_exchange = xt_symbol.split(".")

            if xt_exchange == "ZF" and len(symbol) > 6 and "&" not in symbol:
                product = Product.OPTION
            elif xt_exchange in ("IF", "GF") and "-" in symbol:
                product = Product.OPTION
            elif xt_exchange in ("DF", "INE", "SF") and ("C" in symbol or "P" in symbol) and "SP" not in symbol:
                product = Product.OPTION
            else:
                product = Product.FUTURES

            # 生成并推送合约信息
            if product == Product.OPTION:
                data: dict = xtdata.get_instrument_detail(xt_symbol, True) or {}
            else:
                data = xtdata.get_instrument_detail(xt_symbol) or {}

            if not data["ExpireDate"]:
                if "00" not in symbol:
                    continue

            contract: ContractData = ContractData(
                symbol=symbol,
                exchange=EXCHANGE_XT2VT[xt_exchange],
                name=data["InstrumentName"],
                product=product,
                size=data["VolumeMultiple"],
                pricetick=data["PriceTick"],
                history_data=False,
                gateway_name=self.gateway_name
            )

            symbol_contract_map[contract.vt_symbol] = contract
            symbol_limit_map[contract.vt_symbol] = (data["UpStopPrice"], data["DownStopPrice"])

            self.gateway.on_contract(contract)

    def query_option_contracts(self) -> None:
        """查询期权合约信息"""
        xt_symbols: list[str] = []

        markets: list = [
            "上证期权",
            "深证期权",
            "中金所期权",
            "上期所期权",
            "能源中心期权",
            "大商所期权",
            "郑商所期权",
            "广期所期权"
        ]

        for i in markets:
            names: list = xtdata.get_stock_list_in_sector(i)
            xt_symbols.extend(names)

        for xt_symbol in xt_symbols:
            ""
            _, xt_exchange = xt_symbol.split(".")

            if xt_exchange in {"SHO", "SZO"}:
                contract = process_etf_option(xtdata.get_instrument_detail, xt_symbol, self.gateway_name)
            else:
                contract = process_futures_option(xtdata.get_instrument_detail, xt_symbol, self.gateway_name)

            if contract:
                symbol_contract_map[contract.vt_symbol] = contract

                self.gateway.on_contract(contract)

    def subscribe(self, req: SubscribeRequest) -> None:
        """订阅行情 - 支持基础tick订阅和扩展订阅"""
        if req.vt_symbol not in symbol_contract_map:
            self.gateway.write_log(f"⚠️  合约不存在，无法订阅: {req.vt_symbol}")
            return

        xt_exchange: str = EXCHANGE_VT2XT[req.exchange]
        if xt_exchange in {"SH", "SZ"} and len(req.symbol) > 6:
            xt_exchange += "O"

        xt_symbol: str = req.symbol + "." + xt_exchange

        if xt_symbol not in self.subscribed:
            try:
                # Check if this is an enhanced subscription request
                if isinstance(req, XtSubscribeRequest):
                    self._subscribe_enhanced(req, xt_symbol)
                else:
                    # Default tick subscription for compatibility
                    seq = xtdata.subscribe_quote(stock_code=xt_symbol, period="tick", callback=self.onMarketData)
                    self.subscribed.add(xt_symbol)
                    self.gateway.write_log(f"✅ Tick订阅成功: {xt_symbol}, 订阅号={seq}")
                    
            except Exception as e:
                self.gateway.write_log(f"❌ 订阅失败: {xt_symbol} - {type(e).__name__}: {e}")
    
    def _subscribe_enhanced(self, req: XtSubscribeRequest, xt_symbol: str) -> None:
        """增强订阅 - 支持周期、复权等高级功能"""
        try:
            period = req.period
            dividend_type = req.dividend_type
            start_time = req.start_time
            end_time = req.end_time
            count = req.count
            
            self.gateway.write_log(
                f"增强订阅: {xt_symbol}, "
                f"周期={period}, "
                f"复权={dividend_type if dividend_type else '无'}, "
                f"起始={start_time if start_time else '实时'}, "
                f"结束={end_time if end_time else '实时'}, "
                f"数量={count if count else '实时'}"
            )
            
            # Use subscribe_quote2 for enhanced features
            seq = xtdata.subscribe_quote2(
                stock_code=xt_symbol,
                period=period,
                start_time=start_time,
                end_time=end_time,
                count=count,
                dividend_type=dividend_type,
                callback=self.onMarketData
            )
            
            self.subscribed.add(xt_symbol)
            self.gateway.write_log(f"✅ 订阅成功: {xt_symbol}, 订阅号={seq}")
            
        except RuntimeError as e:
            error_msg = str(e)
            self.gateway.write_log(f"❌ 增强订阅失败: {xt_symbol} - {error_msg}")
            
        except Exception as e:
            self.gateway.write_log(f"❌ 增强订阅异常: {xt_symbol} - {type(e).__name__}: {e}")
    
    def subscribe_l2_thousand(self, req: XtL2SubscribeRequest) -> int:
        """订阅L2千档行情"""
        try:
            xt_exchange: str = EXCHANGE_VT2XT[req.exchange]
            if xt_exchange in {"SH", "SZ"} and len(req.symbol) > 6:
                xt_exchange += "O"
            
            xt_symbol: str = req.symbol + "." + xt_exchange
            
            gear_desc = f"{req.gear_num}档" if req.gear_num else "全部档位"
            self.gateway.write_log(f"订阅L2千档: {xt_symbol}, {gear_desc}")
            
            seq = xtdata.subscribe_l2thousand(
                stock_code=xt_symbol,
                gear_num=req.gear_num,
                callback=req.callback if req.callback else self.onL2ThousandData
            )
            
            self.gateway.write_log(f"✅ L2千档订阅成功: {xt_symbol}, 订阅号={seq}")
            return seq
            
        except RuntimeError as e:
            error_msg = str(e)
            if "no level2 permission" in error_msg:
                self.gateway.write_log(
                    f"❌ L2千档订阅失败: {xt_symbol} - 无L2权限，请确认账户已开通Level-2行情权限"
                )
            else:
                self.gateway.write_log(f"❌ L2千档订阅失败: {xt_symbol} - {error_msg}")
            return -1
            
        except Exception as e:
            self.gateway.write_log(f"❌ L2千档订阅异常: {xt_symbol} - {type(e).__name__}: {e}")
            return -1
    
    def subscribe_whole_quote(self, req: XtWholeQuoteRequest) -> int:
        """订阅全推行情"""
        try:
            self.gateway.write_log(f"订阅全推行情: {req.code_list}")
            
            seq = xtdata.subscribe_whole_quote(
                code_list=req.code_list,
                callback=req.callback if req.callback else self.onWholeQuoteData
            )
            
            self.gateway.write_log(f"✅ 全推行情订阅成功, 订阅号={seq}")
            return seq
            
        except RuntimeError as e:
            error_msg = str(e)
            self.gateway.write_log(f"❌ 全推行情订阅失败: {req.code_list} - {error_msg}")
            return -1
            
        except Exception as e:
            self.gateway.write_log(f"❌ 全推行情订阅异常: {req.code_list} - {type(e).__name__}: {e}")
            return -1
    
    def onL2ThousandData(self, data: dict) -> None:
        """L2千档数据回调"""
        try:
            # Process L2 thousand-level data
            # This can be extended to push to VNPy event system
            for xt_symbol, quotes in data.items():
                if quotes:
                    quote = quotes[0]  # Get the latest quote
                    self.gateway.write_log(
                        f"📊 L2千档更新: {xt_symbol}, "
                        f"时间={quote.get('time', 0)}, "
                        f"买档={len(quote.get('bidPrice', []))}, "
                        f"卖档={len(quote.get('askPrice', []))}"
                    )
        except Exception as e:
            self.gateway.write_log(f"❌ L2千档数据处理异常: {type(e).__name__}: {e}")
    
    def onWholeQuoteData(self, data: dict) -> None:
        """全推行情数据回调"""
        try:
            # Log summary of received data
            from datetime import datetime
            total_count = len(data)
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            self.gateway.write_log(f"📈 全推行情更新 [{current_time}]: 收到 {total_count} 个合约数据")
            
            # Process whole quote data
            # Convert to TickData and push to VNPy
            
            # Add counter for logging
            processed_count = 0
            for xt_symbol, quote in data.items():
                try:
                    symbol, xt_exchange = xt_symbol.split(".")
                    exchange = EXCHANGE_XT2VT.get(xt_exchange)
                    
                    if not exchange:
                        continue
                    
                    vt_symbol = f"{symbol}.{exchange.value}"
                    
                    # Create tick data from whole quote
                    tick = TickData(
                        symbol=symbol,
                        exchange=exchange,
                        datetime=generate_datetime(quote.get("time", 0)),
                        name=symbol_contract_map.get(vt_symbol, ContractData(
                            symbol=symbol,
                            exchange=exchange,
                            name=symbol,
                            product=Product.EQUITY,
                            size=1,
                            pricetick=0.01,
                            gateway_name=self.gateway_name
                        )).name,
                        volume=quote.get("volume", 0),
                        turnover=quote.get("amount", 0),
                        open_price=quote.get("open", 0),
                        high_price=quote.get("high", 0),
                        low_price=quote.get("low", 0),
                        pre_close=quote.get("lastClose", 0),
                        last_price=quote.get("lastPrice", 0),
                        bid_price_1=quote.get("bidPrice", [0])[0] if quote.get("bidPrice") else 0,
                        bid_price_2=quote.get("bidPrice", [0, 0])[1] if len(quote.get("bidPrice", [])) > 1 else 0,
                        bid_price_3=quote.get("bidPrice", [0, 0, 0])[2] if len(quote.get("bidPrice", [])) > 2 else 0,
                        bid_price_4=quote.get("bidPrice", [0, 0, 0, 0])[3] if len(quote.get("bidPrice", [])) > 3 else 0,
                        bid_price_5=quote.get("bidPrice", [0, 0, 0, 0, 0])[4] if len(quote.get("bidPrice", [])) > 4 else 0,
                        ask_price_1=quote.get("askPrice", [0])[0] if quote.get("askPrice") else 0,
                        ask_price_2=quote.get("askPrice", [0, 0])[1] if len(quote.get("askPrice", [])) > 1 else 0,
                        ask_price_3=quote.get("askPrice", [0, 0, 0])[2] if len(quote.get("askPrice", [])) > 2 else 0,
                        ask_price_4=quote.get("askPrice", [0, 0, 0, 0])[3] if len(quote.get("askPrice", [])) > 3 else 0,
                        ask_price_5=quote.get("askPrice", [0, 0, 0, 0, 0])[4] if len(quote.get("askPrice", [])) > 4 else 0,
                        bid_volume_1=quote.get("bidVol", [0])[0] if quote.get("bidVol") else 0,
                        bid_volume_2=quote.get("bidVol", [0, 0])[1] if len(quote.get("bidVol", [])) > 1 else 0,
                        bid_volume_3=quote.get("bidVol", [0, 0, 0])[2] if len(quote.get("bidVol", [])) > 2 else 0,
                        bid_volume_4=quote.get("bidVol", [0, 0, 0, 0])[3] if len(quote.get("bidVol", [])) > 3 else 0,
                        bid_volume_5=quote.get("bidVol", [0, 0, 0, 0, 0])[4] if len(quote.get("bidVol", [])) > 4 else 0,
                        ask_volume_1=quote.get("askVol", [0])[0] if quote.get("askVol") else 0,
                        ask_volume_2=quote.get("askVol", [0, 0])[1] if len(quote.get("askVol", [])) > 1 else 0,
                        ask_volume_3=quote.get("askVol", [0, 0, 0])[2] if len(quote.get("askVol", [])) > 2 else 0,
                        ask_volume_4=quote.get("askVol", [0, 0, 0, 0])[3] if len(quote.get("askVol", [])) > 3 else 0,
                        ask_volume_5=quote.get("askVol", [0, 0, 0, 0, 0])[4] if len(quote.get("askVol", [])) > 4 else 0,
                        gateway_name=self.gateway_name
                    )
                    
                    # Add logging to verify tick routing
                    self.gateway.write_log(f"🔄 推送Tick数据到策略: {tick.vt_symbol} 时间={tick.datetime} 价格={tick.last_price}")
                    self.gateway.on_tick(tick)
                    processed_count += 1
                    
                except Exception as e:
                    self.gateway.write_log(f"❌ 处理全推数据异常: {xt_symbol} - {type(e).__name__}: {e}")
            
            # Log summary of processed data
            self.gateway.write_log(f"✅ 全推行情处理完成: 成功处理 {processed_count} 个合约数据")
                    
        except Exception as e:
            self.gateway.write_log(f"❌ 全推数据回调异常: {type(e).__name__}: {e}")

    def close(self) -> None:
        """关闭连接"""
        pass


class XtTdApi(XtQuantTraderCallback):
    """交易API"""

    def __init__(self, gateway: XtGateway):
        """构造函数"""
        super().__init__()

        self.gateway: XtGateway = gateway
        self.gateway_name: str = gateway.gateway_name

        self.inited: bool = False
        self.connected: bool = False

        self.account_id: str = ""
        self.path: str = ""
        self.account_type: str = ""

        self.order_count: int = 0

        self.active_localid_sysid_map: dict[str, str] = {}

        self.xt_client: XtQuantTrader = None  # type: ignore
        self.xt_account: StockAccount = None  # type: ignore
        
        # 创建专用的 logger
        self._logger = logging.getLogger("XtTdApi")

    def on_connected(self) -> None:
        """
        连接成功推送
        """
        msg = "交易接口连接成功"
        self.gateway.write_log(msg)
        self._logger.info(msg)

    def on_disconnected(self) -> None:
        """连接断开"""
        msg = "交易接口连接断开，请检查与客户端的连接状态"
        self.gateway.write_log(msg)
        self._logger.warning(msg)
        self.connected = False

        # 尝试重连，重连需要更换session_id
        session: int = int(float(datetime.now().strftime("%H%M%S.%f")) * 1000)
        connect_result: int = self.connect(self.path, self.account_id, self.account_type, session)

        if connect_result:
            msg = "交易接口重连失败"
            self.gateway.write_log(msg)
            self._logger.error(msg)
        else:
            msg = "交易接口重连成功"
            self.gateway.write_log(msg)
            self._logger.info(msg)

    def on_stock_trade(self, xt_trade: XtTrade) -> None:
        """成交变动推送"""
        if not xt_trade.order_remark:
            return

        symbol, xt_exchange = xt_trade.stock_code.split(".")

        direction, offset = DIRECTION_XT2VT.get(xt_trade.order_type, (None, None))
        if direction is None:
            return

        trade: TradeData = TradeData(
            symbol=symbol,
            exchange=EXCHANGE_XT2VT[xt_exchange],
            orderid=xt_trade.order_remark,
            tradeid=xt_trade.traded_id,
            direction=direction,
            offset=offset,
            price=xt_trade.traded_price,
            volume=xt_trade.traded_volume,
            datetime=generate_datetime(xt_trade.traded_time, False),
            gateway_name=self.gateway_name
        )

        contract: ContractData = symbol_contract_map.get(trade.vt_symbol, None)  # type: ignore
        if contract:
            trade.price = round_to(trade.price, contract.pricetick)

        self.gateway.on_trade(trade)

    def on_stock_order(self, xt_order: XtOrder) -> None:
        """委托回报推送"""
        # 过滤非VeighNa Trader发出的委托
        if not xt_order.order_remark:
            return

        # 过滤不支持的委托类型
        type: OrderType = ORDERTYPE_XT2VT.get(xt_order.price_type, OrderType.LIMIT)
        if not type:
            return

        direction, offset = DIRECTION_XT2VT.get(xt_order.order_type, (None, None))
        if direction is None:
            return

        symbol, xt_exchange = xt_order.stock_code.split(".")

        order: OrderData = OrderData(
            symbol=symbol,
            exchange=EXCHANGE_XT2VT[xt_exchange],
            orderid=xt_order.order_remark,
            direction=direction,
            offset=offset,
            type=type,                  # 目前测出来与文档不同，限价返回50，市价返回88
            price=xt_order.price,
            volume=xt_order.order_volume,
            traded=xt_order.traded_volume,
            status=STATUS_XT2VT.get(xt_order.order_status, Status.SUBMITTING),
            datetime=generate_datetime(xt_order.order_time, False),
            gateway_name=self.gateway_name
        )

        if order.is_active():
            self.active_localid_sysid_map[xt_order.order_remark] = xt_order.order_sysid
        else:
            self.active_localid_sysid_map.pop(xt_order.order_remark, None)

        contract: ContractData = symbol_contract_map.get(order.vt_symbol, None)  # type: ignore
        if contract:
            order.price = round_to(order.price, contract.pricetick)

        self.gateway.on_order(order)

    def on_query_order_async(self, xt_orders: list[XtOrder]) -> None:
        """委托信息异步查询回报"""
        if not xt_orders:
            return

        for data in xt_orders:
            self.on_stock_order(data)

        self.gateway.write_log("委托信息查询成功")

    def on_query_asset_async(self, xt_asset: XtAsset) -> None:
        """资金信息异步查询回报"""
        self.gateway.write_log(f"接收到账户资金回调，xt_asset类型: {type(xt_asset)}")
        
        if not xt_asset:
            self.gateway.write_log("资金查询返回空数据")
            return

        try:
            # 打印接收到的资产对象的所有可用属性，用于调试
            asset_attributes = dir(xt_asset)
            # self.gateway.write_log(f"账户资产对象属性: {asset_attributes}")
            
            # 使用getattr处理不同版本的字段名称，增加兼容性
            account_id = getattr(xt_asset, 'account_id', '')
            total_asset = getattr(xt_asset, 'total_asset', 0)
            frozen_cash = getattr(xt_asset, 'frozen_cash', 0)
            available_cash = getattr(xt_asset, 'available_cash', getattr(xt_asset, 'cash', 0))
            market_value = getattr(xt_asset, 'market_value', 0)
            
            self.gateway.write_log(f"解析账户数据: account_id={account_id}, total_asset={total_asset}, frozen_cash={frozen_cash}, available_cash={available_cash}, market_value={market_value}")
            
            account: AccountData = AccountData(
                accountid=account_id,
                balance=total_asset,
                frozen=frozen_cash,
                gateway_name=self.gateway_name
            )
            account.available = available_cash
            account.position_value = market_value
            
            self.gateway.write_log(f"调用gateway.on_account前: {account}")
            self.gateway.on_account(account)
            self.gateway.write_log(f"账户资金查询成功并触发事件: {account.accountid}")
            
            # 直接检查gateway.accounts字典是否已更新
            if hasattr(self.gateway, 'accounts'):
                self.gateway.write_log(f"Gateway账户字典长度: {len(self.gateway.accounts)}")
                for acc_id, acc in self.gateway.accounts.items():
                    self.gateway.write_log(f"Gateway中账户: {acc_id} - 总资产: {acc.total_value}")
                    
        except Exception as e:
            self.gateway.write_log(f"处理账户资金数据异常: {str(e)}")
            import traceback
            self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")

    def on_query_positions_async(self, xt_positions: list[XtPosition]) -> None:
        """持仓信息异步查询回报"""
        self.gateway.write_log(f"接收到持仓回调，xt_positions类型: {type(xt_positions)}, 长度: {len(xt_positions) if xt_positions else 0}")
        
        if not xt_positions:
            self.gateway.write_log("持仓查询返回空数据")
            return

        try:
            position_count = 0
            for i, xt_position in enumerate(xt_positions):
                try:
                    self.gateway.write_log(f"处理持仓项 {i+1}/{len(xt_positions)}, 类型: {type(xt_position)}")
                    
                    # 打印持仓对象的所有可用属性
                    pos_attributes = dir(xt_position)
                    # self.gateway.write_log(f"持仓对象属性: {pos_attributes}")
                    
                    if self.account_type == "STOCK":
                        direction: Direction = Direction.NET
                    else:
                        direction = POSDIRECTION_XT2VT.get(getattr(xt_position, 'direction', 0), Direction.NET)

                    self.gateway.write_log(f"持仓方向: {direction}")
                    
                    if not direction:
                        self.gateway.write_log("跳过无效方向的持仓")
                        continue

                    # 获取股票代码和交易所信息，增加错误处理
                    stock_code = getattr(xt_position, 'stock_code', '')
                    self.gateway.write_log(f"持仓股票代码: {stock_code}")
                    
                    if '.' not in stock_code:
                        self.gateway.write_log(f"股票代码格式不正确: {stock_code}")
                        continue
                        
                    symbol_parts = stock_code.split('.')
                    if len(symbol_parts) < 2:
                        self.gateway.write_log(f"股票代码缺少交易所信息: {stock_code}")
                        continue
                        
                    symbol = symbol_parts[0]
                    xt_exchange = symbol_parts[1]
                    exchange = EXCHANGE_XT2VT.get(xt_exchange, Exchange.SSE)
                    
                    self.gateway.write_log(f"解析后的合约信息: symbol={symbol}, exchange={exchange}")

                    # 创建持仓数据对象，使用getattr确保字段存在
                    volume = getattr(xt_position, 'volume', 0)
                    can_use_volume = getattr(xt_position, 'can_use_volume', getattr(xt_position, 'volume', 0) - getattr(xt_position, 'frozen_volume', 0))
                    price = getattr(xt_position, 'price', getattr(xt_position, 'open_price', 0))
                    yd_volume = getattr(xt_position, 'yd_volume', 0)
                    
                    self.gateway.write_log(f"持仓数据: volume={volume}, can_use_volume={can_use_volume}, price={price}, yd_volume={yd_volume}")
                    
                    position: PositionData = PositionData(
                        symbol=symbol,
                        exchange=exchange,
                        direction=direction,
                        volume=volume,
                        price=price,
                        gateway_name=self.gateway_name
                    )
                    
                    position.yd_volume = yd_volume
                    position.frozen = volume - can_use_volume
                    
                    self.gateway.write_log(f"调用gateway.on_position前: {position}")
                    self.gateway.on_position(position)
                    position_count += 1
                    self.gateway.write_log(f"成功处理并触发持仓事件: {position.vt_symbol}, 累计处理: {position_count}")
                    
                    # 直接检查gateway.positions字典是否已更新
                    if hasattr(self.gateway, 'positions'):
                        self.gateway.write_log(f"Gateway持仓字典长度: {len(self.gateway.positions)}")
                        
                except Exception as e:
                    self.gateway.write_log(f"处理单个持仓数据异常: {str(e)}")
                    import traceback
                    self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
                    continue
                    
            self.gateway.write_log(f"持仓信息查询成功，共{position_count}条记录")
        except Exception as e:
            self.gateway.write_log(f"处理持仓数据异常: {str(e)}")
            import traceback
            self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")

    def on_order_error(self, xt_error: XtOrderError) -> None:
        """委托失败推送"""
        order: OrderData = self.gateway.get_order(xt_error.order_remark)
        if order:
            order.status = Status.REJECTED
            self.gateway.on_order(order)

        self.gateway.write_log(f"交易委托失败, 错误代码{xt_error.error_id}, 错误信息{xt_error.error_msg}")

    def on_cancel_error(self, xt_error: XtCancelError) -> None:
        """撤单失败推送"""
        self.gateway.write_log(f"交易撤单失败, 错误代码{xt_error.error_id}, 错误信息{xt_error.error_msg}")

    def on_order_stock_async_response(self, response: XtOrderResponse) -> None:
        """异步下单回报推送"""
        if response.error_msg:
            self.gateway.write_log(f"委托请求提交失败：{response.error_msg}，本地委托号{response.order_remark}")
        else:
            self.gateway.write_log(f"委托请求提交成功，本地委托号{response.order_remark}")

    def on_cancel_order_stock_async_response(self, response: XtCancelOrderResponse) -> None:
        """异步撤单回报推送"""
        if response.error_msg:
            self.gateway.write_log(f"撤单请求提交失败：{response.error_msg}，系统委托号{response.order_sysid}")
        else:
            self.gateway.write_log(f"撤单请求提交成功，系统委托号{response.order_sysid}")

    def connect(self, path: str, accountid: str, account_type: str, session: int = 0) -> int:
        """发起连接"""
        self.inited = True
        self.account_id = accountid
        self.path = path
        self.account_type = account_type

        # 创建客户端和账号实例
        if not session:
            session = int(float(datetime.now().strftime("%H%M%S.%f")) * 1000)

        self.xt_client = XtQuantTrader(self.path, session)

        self.xt_account = StockAccount(self.account_id, account_type=self.account_type)

        # 注册回调接口
        self.xt_client.register_callback(self)

        # 启动交易线程
        self.xt_client.start()

        # 建立交易连接，返回0表示连接成功
        connect_result: int = self.xt_client.connect()
        if connect_result:
            self.gateway.write_log("交易接口连接失败")
            return connect_result

        self.connected = True
        self.gateway.write_log("交易接口连接成功")

        # 订阅交易回调推送
        subscribe_result: int = self.xt_client.subscribe(self.xt_account)
        if subscribe_result:
            self.gateway.write_log("交易推送订阅失败")
            return -1

        self.gateway.write_log("交易推送订阅成功")

        # 初始化数据查询
        self.query_account()
        self.query_position()
        self.query_order()
        self.query_trade()

        return connect_result

    def new_orderid(self) -> str:
        """生成本地委托号"""
        prefix: str = datetime.now().strftime("1%m%d%H%M%S")

        self.order_count += 1
        suffix: str = str(self.order_count).rjust(6, "0")

        orderid: str = prefix + suffix
        return orderid

    def send_order(self, req: OrderRequest) -> str:
        """委托下单"""
        contract: ContractData = symbol_contract_map.get(req.vt_symbol, None)
        if not contract:
            self.gateway.write_log(f"找不到该合约{req.vt_symbol}")
            return ""

        if contract.exchange not in {Exchange.SSE, Exchange.SZSE, Exchange.BSE}:
            self.gateway.write_log(f"不支持的合约{req.vt_symbol}")
            return ""

        if req.type not in {OrderType.LIMIT}:
            self.gateway.write_log(f"不支持的委托类型: {req.type.value}")
            return ""

        if req.offset == Offset.NONE and contract.product == Product.OPTION:
            self.gateway.write_log("委托失败，期权交易需要选择开平方向")
            return ""

        stock_code: str = req.symbol + "." + EXCHANGE_VT2XT[req.exchange]
        if self.account_type == "STOCK_OPTION":
            stock_code += "O"

        # 现货委托不考虑开平
        if contract.product == Product.OPTION:
            xt_direction: tuple = (req.direction, req.offset)
        else:
            xt_direction = (req.direction, Offset.NONE)

        orderid: str = self.new_orderid()

        self.xt_client.order_stock_async(
            account=self.xt_account,
            stock_code=stock_code,
            order_type=DIRECTION_VT2XT[xt_direction],
            order_volume=int(req.volume),
            price_type=ORDERTYPE_VT2XT[(req.exchange, req.type)],
            price=req.price,
            strategy_name=req.reference,
            order_remark=orderid
        )

        order: OrderData = req.create_order_data(orderid, self.gateway_name)
        self.gateway.on_order(order)

        vt_orderid: str = order.vt_orderid

        return vt_orderid

    def cancel_order(self, req: CancelRequest) -> None:
        """委托撤单"""
        sysid: str | None = self.active_localid_sysid_map.get(req.orderid, None)
        if not sysid:
            self.gateway.write_log("撤单失败，找不到委托号")
            return

        if req.exchange == Exchange.SSE:
            market: int = 0
        else:
            market = 1

        self.xt_client.cancel_order_stock_sysid_async(self.xt_account, market, sysid)

    def query_position(self) -> None:
        """查询持仓"""
        self.gateway.write_log(f"开始查询持仓，连接状态: {self.connected}, xt_account: {self.xt_account}, 回调函数: {self.on_query_positions_async}")
        
        if self.connected:
            try:
                # 添加调试日志，检查xt_client是否可用
                if hasattr(self, 'xt_client'):
                    self.gateway.write_log("xt_client存在，发送持仓查询请求")
                    result = self.xt_client.query_stock_positions_async(self.xt_account, self.on_query_positions_async)
                    self.gateway.write_log(f"持仓查询请求已发送，返回值: {result}")
                else:
                    self.gateway.write_log("错误: xt_client不存在")
            except Exception as e:
                self.gateway.write_log(f"发送持仓查询请求异常: {str(e)}")
                import traceback
                self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
        else:
            self.gateway.write_log("无法查询持仓: 连接未建立")

    def query_account(self) -> None:
        """查询账户资金"""
        self.gateway.write_log(f"开始查询账户资金，连接状态: {self.connected}, xt_account: {self.xt_account}, 回调函数: {self.on_query_asset_async}")
        
        if self.connected:
            try:
                # 添加调试日志，检查xt_client是否可用
                if hasattr(self, 'xt_client'):
                    self.gateway.write_log("xt_client存在，发送账户资金查询请求")
                    result = self.xt_client.query_stock_asset_async(self.xt_account, self.on_query_asset_async)
                    self.gateway.write_log(f"账户资金查询请求已发送，返回值: {result}")
                else:
                    self.gateway.write_log("错误: xt_client不存在")
            except Exception as e:
                self.gateway.write_log(f"发送账户资金查询请求异常: {str(e)}")
                import traceback
                self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
        else:
            self.gateway.write_log("无法查询账户资金: 连接未建立")

    def query_order(self) -> None:
        """查询委托信息 - 使用同步查询方法，与qmt_trader_tool.py保持一致"""
        self.gateway.write_log(f"开始查询订单，连接状态: {self.connected}, xt_account: {self.xt_account}")
        
        if self.connected:
            try:
                # 添加调试日志，检查xt_client是否可用
                if hasattr(self, 'xt_client'):
                    self.gateway.write_log("xt_client存在，发送订单查询请求")
                    
                    # 改用同步查询方法，与qmt_trader_tool.py保持一致
                    orders = self.xt_client.query_stock_orders(self.xt_account)
                    self.gateway.write_log(f"同步查询订单成功，返回订单数量: {len(orders) if orders else 0}")
                    
                    # 直接处理查询结果
                    if orders:
                        self.gateway.write_log(f"开始处理{len(orders)}条订单数据")
                        for order in orders:
                            # 打印订单对象的所有属性，帮助调试
                            order_attributes = dir(order)
                            # self.gateway.write_log(f"订单对象属性: {order_attributes}")
                            
                            # 获取订单相关数据，使用getattr确保安全访问
                            stock_code = getattr(order, 'stock_code', '')
                            if not stock_code:
                                self.gateway.write_log("跳过无股票代码的订单记录")
                                continue
                                
                            symbol, xt_exchange = stock_code.split(".")
                            
                            # 获取订单相关字段，使用getattr确保安全访问
                            order_id = getattr(order, 'order_id', getattr(order, 'order_remark', ''))
                            sysid = getattr(order, 'order_id', getattr(order, 'order_sysid', ''))
                            order_status = getattr(order, 'order_status', '')
                            side = getattr(order, 'side', getattr(order, 'order_type', ''))
                            price = getattr(order, 'price', 0)
                            volume = getattr(order, 'volume', 0)
                            traded_volume = getattr(order, 'traded_volume', 0)
                            order_time = getattr(order, 'order_time', 0)
                            
                            # 更新本地委托号到系统委托号的映射
                            if order_id and sysid:
                                self.active_localid_sysid_map[order_id] = sysid
                            
                            # 映射委托方向
                            if side == xtconstant.STOCK_BUY:
                                direction = Direction.LONG
                                offset = Offset.NONE
                            elif side == xtconstant.STOCK_SELL:
                                direction = Direction.SHORT
                                offset = Offset.NONE
                            else:
                                # 尝试使用原有映射
                                direction_offset = DIRECTION_XT2VT.get(side, (None, None))
                                if direction_offset[0] is None:
                                    self.gateway.write_log(f"未知的委托方向: {side}")
                                    continue
                                direction, offset = direction_offset
                            
                            # 映射委托状态
                            status = STATUS_XT2VT.get(order_status, Status.SUBMITTING)
                            
                            self.gateway.write_log(f"处理订单: {symbol}.{xt_exchange}, 状态={status}, 价格={price}, 数量={volume}, 已成交={traded_volume}")
                            
                            # 创建订单数据对象
                            order_data = OrderData(
                                symbol=symbol,
                                exchange=EXCHANGE_XT2VT.get(xt_exchange, Exchange.SSE),
                                orderid=order_id,
                                type=OrderType.LIMIT,
                                direction=direction,
                                offset=offset,
                                price=price,
                                volume=volume,
                                traded=traded_volume,
                                status=status,
                                datetime=generate_datetime(order_time, False),
                                gateway_name=self.gateway_name
                            )
                            
                            self.gateway.on_order(order_data)
                            # 直接更新gateway的orders字典，确保数据被正确存储
                            if hasattr(self.gateway, 'orders'):
                                self.gateway.orders[order_data.vt_orderid] = order_data
                    else:
                        self.gateway.write_log("未查询到订单数据")
                else:
                    self.gateway.write_log("错误: xt_client不存在")
            except Exception as e:
                self.gateway.write_log(f"发送订单查询请求异常: {str(e)}")
                import traceback
                self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
        else:
            self.gateway.write_log("无法查询订单: 连接未建立")

    def on_query_trades_async(self, trade_list, error_info):
        """异步查询成交数据回调"""
        self.gateway.write_log(f"收到成交查询回调: 数据长度={len(trade_list) if trade_list else 0}, 错误信息={error_info}")
        
        if not trade_list or error_info:
            self.gateway.write_log(f"成交查询失败或无数据: {error_info}")
            return
            
        try:
            for trade in trade_list:
                trade_id = getattr(trade, 'trade_id', getattr(trade, 'trade_sysid', ''))
                trade_status = getattr(trade, 'trade_status', '')
                side = getattr(trade, 'side', getattr(trade, 'trade_type', ''))
                price = getattr(trade, 'price', 0)
                volume = getattr(trade, 'volume', 0)
                trade_time = getattr(trade, 'trade_time', 0)
                order_id = getattr(trade, 'order_id', getattr(trade, 'order_sysid', ''))
                symbol = getattr(trade, 'stock_code', '')
                xt_exchange = getattr(trade, 'exchange', '')
                
                # 更新本地委托号到系统委托号的映射
                if order_id and trade_id:
                    self.active_localid_sysid_map[order_id] = trade_id
                
                # 映射委托方向
                if side == xtconstant.STOCK_BUY:
                    direction = Direction.LONG
                elif side == xtconstant.STOCK_SELL:
                    direction = Direction.SHORT
                else:
                    # 尝试使用原有映射
                    direction = DIRECTION_XT2VT.get(side, (None, None))[0]
                    if direction is None:
                        self.gateway.write_log(f"未知的委托方向: {side}")
                        continue
                
                # 创建成交数据对象
                trade_data = TradeData(
                    symbol=symbol,
                    exchange=EXCHANGE_XT2VT.get(xt_exchange, Exchange.SSE),
                    orderid=order_id,
                    tradeid=trade_id,
                    direction=direction,
                    price=price,
                    volume=volume,
                    datetime=generate_datetime(trade_time, False),
                    gateway_name=self.gateway_name
                )
                
                self.gateway.on_trade(trade_data)
                # 直接更新gateway的trades字典，确保数据被正确存储
                if hasattr(self.gateway, 'trades'):
                    self.gateway.trades[trade_data.vt_tradeid] = trade_data
        except Exception as e:
            self.gateway.write_log(f"处理成交数据时出错: {str(e)}")
            import traceback
            self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")

    def query_order(self) -> None:
        """查询委托信息"""
        if not self.xt_client or not self.xt_account:
            return

        self.gateway.write_log("开始查询订单，连接状态: {}, xt_account: {}".format(self.connected, self.xt_account))
        
        try:
            # 同步查询所有订单
            xt_orders: list[XtOrder] = self.xt_client.query_stock_orders(self.xt_account)
            self.gateway.write_log(f"xt_client存在，发送订单查询请求")
            
            if xt_orders is not None:
                order_count = len(xt_orders)
                self.gateway.write_log(f"同步查询订单成功，返回订单数量: {order_count}")
                
                if order_count > 0:
                    self.gateway.write_log(f"开始处理{order_count}条订单数据")
                    for i, xt_order in enumerate(xt_orders):
                        try:
                            # 打印订单的详细信息用于调试
                            self.gateway.write_log(f"处理订单: {xt_order.stock_code}, 状态={STATUS_XT2VT.get(xt_order.order_status, Status.SUBMITTING)}, 价格={xt_order.price}, 数量={xt_order.order_volume}, 已成交={xt_order.traded_volume}")
                            
                            # 调用处理函数
                            self.on_stock_order(xt_order)
                        except Exception as e:
                            self.gateway.write_log(f"处理单个订单时出错: {str(e)}")
                            continue
                else:
                    self.gateway.write_log("未查询到订单数据")
            else:
                self.gateway.write_log("订单查询返回None")
                
        except Exception as e:
            self.gateway.write_log(f"查询订单异常: {str(e)}")
            import traceback
            self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
    
    def on_query_order_async(self, order_list, error_info):
        """异步查询委托数据回调"""
        self.gateway.write_log(f"收到订单查询回调: 数据长度={len(order_list) if order_list else 0}, 错误信息={error_info}")
        
        if not order_list or error_info:
            self.gateway.write_log(f"订单查询失败或无数据: {error_info}")
            return
            
        try:
            for order in order_list:
                # 打印订单对象的所有属性，帮助调试
                order_attributes = dir(order)
                # self.gateway.write_log(f"订单对象属性: {order_attributes}")
                
                # 获取订单相关数据，使用getattr确保安全访问
                stock_code = getattr(order, 'stock_code', '')
                if not stock_code:
                    self.gateway.write_log("跳过无股票代码的订单记录")
                    continue
                    
                symbol, xt_exchange = stock_code.split(".")
                
                # 获取订单相关字段，使用getattr确保安全访问
                order_id = getattr(order, 'order_id', getattr(order, 'order_remark', ''))
                sysid = getattr(order, 'order_id', getattr(order, 'order_sysid', ''))
                order_status = getattr(order, 'order_status', '')
                side = getattr(order, 'side', getattr(order, 'order_type', ''))
                price = getattr(order, 'price', 0)
                volume = getattr(order, 'volume', 0)
                traded_volume = getattr(order, 'traded_volume', 0)
                order_time = getattr(order, 'order_time', 0)
                
                # 更新本地委托号到系统委托号的映射
                if order_id and sysid:
                    self.active_localid_sysid_map[order_id] = sysid
                
                # 映射委托方向
                if side == xtconstant.STOCK_BUY:
                    direction = Direction.LONG
                    offset = Offset.NONE
                elif side == xtconstant.STOCK_SELL:
                    direction = Direction.SHORT
                    offset = Offset.NONE
                else:
                    # 尝试使用原有映射
                    direction_offset = DIRECTION_XT2VT.get(side, (None, None))
                    if direction_offset[0] is None:
                        self.gateway.write_log(f"未知的委托方向: {side}")
                        continue
                    direction, offset = direction_offset
                
                # 映射委托状态
                status = STATUS_XT2VT.get(order_status, Status.SUBMITTING)
                
                self.gateway.write_log(f"处理订单: {symbol}.{xt_exchange}, 状态={status}, 价格={price}, 数量={volume}, 已成交={traded_volume}")
                
                # 创建订单数据对象
                order_data = OrderData(
                    symbol=symbol,
                    exchange=EXCHANGE_XT2VT.get(xt_exchange, Exchange.SSE),
                    orderid=order_id,
                    type=OrderType.LIMIT,
                    direction=direction,
                    offset=offset or Offset.NONE,
                    price=price,
                    volume=volume,
                    traded=traded_volume,
                    status=status,
                    datetime=generate_datetime(order_time, False),
                    gateway_name=self.gateway_name
                )
                
                self.gateway.on_order(order_data)
                # 直接更新gateway的orders字典，确保数据被正确存储
                if hasattr(self.gateway, 'orders'):
                    self.gateway.orders[order_data.vt_orderid] = order_data
                
            self.gateway.write_log(f"订单信息查询成功，共{len(order_list)}条记录")
        except Exception as e:
            self.gateway.write_log(f"处理订单数据异常: {str(e)}")
            import traceback
            self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
    
    def query_trade(self) -> None:
        """查询成交信息 - 使用同步查询方法，与qmt_trader_tool.py保持一致"""
        self.gateway.write_log(f"开始查询成交，连接状态: {self.connected}, xt_account: {self.xt_account}")
        
        if self.connected:
            try:
                # 添加调试日志，检查xt_client是否可用
                if hasattr(self, 'xt_client'):
                    self.gateway.write_log("xt_client存在，发送成交查询请求")
                    
                    # 改用同步查询方法，与qmt_trader_tool.py保持一致
                    trades = self.xt_client.query_stock_trades(self.xt_account)
                    self.gateway.write_log(f"同步查询成交成功，返回成交数量: {len(trades) if trades else 0}")
                    
                    # 直接处理查询结果
                    if trades:
                        self.gateway.write_log(f"开始处理{len(trades)}条成交数据")
                        for trade in trades:
                            # 打印成交对象的所有属性，帮助调试
                            trade_attributes = dir(trade)
                            # self.gateway.write_log(f"成交对象属性: {trade_attributes}")
                            
                            # 获取股票代码，使用getattr确保安全访问
                            stock_code = getattr(trade, 'stock_code', '')
                            if not stock_code:
                                self.gateway.write_log("跳过无股票代码的成交记录")
                                continue
                                
                            symbol, xt_exchange = stock_code.split(".")
                            
                            # 获取成交相关数据，使用getattr确保安全访问
                            order_id = getattr(trade, 'order_id', getattr(trade, 'order_remark', ''))
                            trade_id = getattr(trade, 'trade_id', getattr(trade, 'traded_id', ''))
                            direction_str = getattr(trade, 'side', getattr(trade, 'order_type', ''))
                            traded_price = getattr(trade, 'price', getattr(trade, 'traded_price', 0))
                            traded_volume = getattr(trade, 'volume', getattr(trade, 'traded_volume', 0))
                            traded_time = getattr(trade, 'trade_time', getattr(trade, 'traded_time', 0))
                            
                            # 根据qmt_trader_tool.py中的实现，调整方向映射
                            if direction_str == xtconstant.STOCK_BUY:
                                direction = Direction.LONG
                                offset = Offset.NONE
                            elif direction_str == xtconstant.STOCK_SELL:
                                direction = Direction.SHORT
                                offset = Offset.NONE
                            else:
                                # 尝试使用原有映射
                                direction_offset = DIRECTION_XT2VT.get(direction_str, (None, None))
                                if direction_offset[0] is None:
                                    self.gateway.write_log(f"未知的成交方向: {direction_str}")
                                    continue
                                direction, offset = direction_offset
                            
                            self.gateway.write_log(f"处理成交: {symbol}.{xt_exchange}, 价格={traded_price}, 数量={traded_volume}, 时间={traded_time}")
                            
                            trade_data = TradeData(
                                symbol=symbol,
                                exchange=EXCHANGE_XT2VT.get(xt_exchange, Exchange.SSE),
                                orderid=order_id,
                                tradeid=trade_id,
                                direction=direction,
                                offset=offset,
                                price=traded_price,
                                volume=traded_volume,
                                datetime=generate_datetime(traded_time, False),
                                gateway_name=self.gateway_name
                            )
                            
                            contract = symbol_contract_map.get(trade_data.vt_symbol, None)
                            if contract:
                                trade_data.price = round_to(trade_data.price, contract.pricetick)
                            
                            self.gateway.on_trade(trade_data)
                            # 直接更新gateway的trades字典，确保数据被正确存储
                            if hasattr(self.gateway, 'trades'):
                                self.gateway.trades[trade_data.vt_tradeid] = trade_data
                    else:
                        self.gateway.write_log("未查询到成交数据")
                else:
                    self.gateway.write_log("错误: xt_client不存在")
            except Exception as e:
                self.gateway.write_log(f"发送成交查询请求异常: {str(e)}")
                import traceback
                self.gateway.write_log(f"异常堆栈: {traceback.format_exc()}")
        else:
            self.gateway.write_log("无法查询成交: 连接未建立")


    def close(self) -> None:
        """关闭连接"""
        if self.inited:
            self.xt_client.stop()


def generate_datetime(timestamp: int, millisecond: bool = True) -> datetime:
    """生成本地时间"""
    if millisecond:
        dt: datetime = datetime.fromtimestamp(timestamp / 1000)
    else:
        dt = datetime.fromtimestamp(timestamp)
    dt = dt.replace(tzinfo=CHINA_TZ)
    return dt


def process_etf_option(get_instrument_detail: Callable, xt_symbol: str, gateway_name: str) -> ContractData | None:
    """处理ETF期权"""
    # 拆分XT代码
    symbol, xt_exchange = xt_symbol.split(".")

    # 筛选期权合约合约（ETF期权代码为8位）
    if len(symbol) != 8:
        return None

    # 查询转换数据
    data: dict = get_instrument_detail(xt_symbol, True)

    name: str = data["InstrumentName"]
    if "购" in name:
        option_type = OptionType.CALL
    elif "沽" in name:
        option_type = OptionType.PUT
    else:
        return None

    if "A" in name:
        option_index = str(data["OptExercisePrice"]) + "-A"
    else:
        option_index = str(data["OptExercisePrice"]) + "-M"

    contract: ContractData = ContractData(
        symbol=data["InstrumentID"],
        exchange=EXCHANGE_XT2VT[xt_exchange],
        name=data["InstrumentName"],
        product=Product.OPTION,
        size=data["VolumeMultiple"],
        pricetick=data["PriceTick"],
        min_volume=data["MinLimitOrderVolume"],
        option_strike=data["OptExercisePrice"],
        option_listed=datetime.strptime(data["OpenDate"], "%Y%m%d"),
        option_expiry=datetime.strptime(data["ExpireDate"], "%Y%m%d"),
        option_portfolio=data["OptUndlCode"] + "_O",
        option_index=option_index,
        option_type=option_type,
        option_underlying=data["OptUndlCode"] + "-" + str(data["ExpireDate"])[:6],
        gateway_name=gateway_name
    )

    symbol_limit_map[contract.vt_symbol] = (data["UpStopPrice"], data["DownStopPrice"])

    return contract


def process_futures_option(get_instrument_detail: Callable, xt_symbol: str, gateway_name: str) -> ContractData | None:
    """处理期货期权"""
    # 筛选期权合约
    data: dict = get_instrument_detail(xt_symbol, True)

    option_strike: float = data["OptExercisePrice"]
    if not option_strike:
        return None

    # 拆分XT代码
    symbol, xt_exchange = xt_symbol.split(".")

    # 移除产品前缀
    for _ix, w in enumerate(symbol):
        if w.isdigit():
            break

    suffix: str = symbol[_ix:]

    # 过滤非期权合约
    if "(" in symbol or " " in symbol:
        return None

    # 判断期权类型
    if "C" in suffix:
        option_type = OptionType.CALL
    elif "P" in suffix:
        option_type = OptionType.PUT
    else:
        return None

    # 获取期权标的
    if "-" in symbol:
        option_underlying: str = symbol.split("-")[0]
    else:
        option_underlying = data["OptUndlCode"]

    # 转换数据
    contract: ContractData = ContractData(
        symbol=data["InstrumentID"],
        exchange=EXCHANGE_XT2VT[xt_exchange],
        name=data["InstrumentName"],
        product=Product.OPTION,
        size=data["VolumeMultiple"],
        pricetick=data["PriceTick"],
        min_volume=data["MinLimitOrderVolume"],
        option_strike=data["OptExercisePrice"],
        option_listed=datetime.strptime(data["OpenDate"], "%Y%m%d"),
        option_expiry=datetime.strptime(data["ExpireDate"], "%Y%m%d"),
        option_index=str(data["OptExercisePrice"]),
        option_type=option_type,
        option_underlying=option_underlying,
        gateway_name=gateway_name
    )

    if contract.exchange == Exchange.CZCE:
        contract.option_portfolio = data["ProductID"][:-1]
    else:
        contract.option_portfolio = data["ProductID"]

    symbol_limit_map[contract.vt_symbol] = (data["UpStopPrice"], data["DownStopPrice"])

    return contract
